#include "stdafx.h"
#include "DBServer.h"
#include <EndianCast.h>
#include "RoleMgr.h"
#include "RoleMgrEvents.h"

CDBServer * CDBServer::m_pInstance = NULL;


CDBServer::CDBServer(utility::network::pipe * pPipe)
    : IServer(pPipe)
{
    m_oDBProto.Init();
}


CDBServer::~CDBServer(void)
{
}

CDBServer * CDBServer::CreateInstance( utility::network::pipe * pPipe )
{
    if (m_pInstance == NULL)
        m_pInstance = new CDBServer(pPipe);
    return m_pInstance;
}

CDBServer * CDBServer::Instance()
{
    return m_pInstance;        
}

void CDBServer::DestroyInstance()
{
    delete m_pInstance;
    m_pInstance;
}

void CDBServer::Release()
{
    DestroyInstance();
}

void CDBServer::on_receive( const char * message, uint32 message_length )
{
    if (message_length < sizeof(uint32))
        return;
    uint32 nMsgID = ntohl(*((int *)message));

    try{
        m_oDBProto.Decode(nMsgID, message + sizeof(nMsgID), message_length - sizeof(nMsgID), this);
    }
    catch(...)
    {
        LOG(CRITICAL) << "receive error: MsgID=" << nMsgID << ", Length="<<message_length;
    }
}

void CDBServer::on_established()
{
    LOG(INFO) << "Connected with database server " << utility::network::idtoa(m_pPipe->get_remote_id());
}

void CDBServer::on_disconnected()
{

}

void CDBServer::on_error( int32 error_code, const char * error_message )
{

}

bool CDBServer::Send( uint32 MsgID, ::google::protobuf::Message * pMessage )
{
    size_t nBufSize = pMessage->ByteSize() + sizeof(uint32);
    char * pBuf = (char *)alloca(nBufSize);

    uint32 * pHeader = (uint32*)pBuf;
    *pHeader = htonl(MsgID);

    void * pMsg = (void*)(pBuf + sizeof(uint32));

    bool bFlag = pMessage->SerializeToArray(pMsg, nBufSize - sizeof(uint32));
    if (!bFlag)
    {
        LOG(CRITICAL) << "failed to serialize PB Message to array. Type name is "<< pMessage->GetTypeName();
        return false;
    }

    send(pBuf, nBufSize);

    return true;
}

void CDBServer::OnGetRoleData( shared_ptr<PKG_ROLEDATA_NTF> pkg )
{
    TEvent event(new CGetRoleDataEvent(shared_from_this(), pkg));
    SendEvent(CRoleMgrActor::Instance(), event);
}
